package com.mentalhealthplatform.global.rbac.service.relation;

import com.mentalhealthplatform.global.rbac.dto.normal.ButtonDTO;
import com.mentalhealthplatform.global.rbac.dto.normal.MenuDTO;
import com.mentalhealthplatform.global.rbac.dto.normal.PermissionDTO;
import com.mentalhealthplatform.global.rbac.model.ButtonComponent;
import com.mentalhealthplatform.global.rbac.model.Menu;
import com.mentalhealthplatform.global.rbac.model.Role;
import com.mentalhealthplatform.global.rbac.repository.ButtonComponentRepository;
import com.mentalhealthplatform.global.rbac.repository.MenuRepository;
import com.mentalhealthplatform.global.rbac.repository.RoleRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class RoleMenuService {

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private MenuRepository menuRepository;

    @Autowired
    private ButtonComponentRepository buttonComponentRepository;

    //////////////////////////
    ///
    /// 复杂方法
    ///
    /////////////////////////
    // 获取指定角色的菜单、子菜单和按钮/组件的层级结构
    public Set<MenuDTO> getRoleMenuHierarchy(Long roleId) {
        // 获取角色对象
        Role role = roleRepository.findById(roleId).orElseThrow(() -> new RuntimeException("Role not found"));


        // 获取角色拥有的顶级菜单
        Set<Menu> roleMenus = role.getMenus().stream()
                .filter(menu -> menu.getParentMenu() == null && menu.isStatus()) // 过滤掉状态为false的菜单
                .collect(Collectors.toSet());

        // 构建菜单层级结构
        return roleMenus.stream()
                .map(menu -> buildMenuHierarchy(menu, role))
                .collect(Collectors.toSet());
    }

    // 递归构建菜单和子菜单的层级结构
    private MenuDTO buildMenuHierarchy(Menu menu, Role role) {
        // 如果菜单不可见，跳过
        if (!menu.isVisible()) {
            return null;
        }

        // 角色是否拥有该菜单的访问权限
        boolean hasAccess = role.getMenus().contains(menu);

        // 如果角色没有访问该菜单的权限，直接跳过子菜单和按钮的检查
        if (!hasAccess) {
            return null;
        }

        // 递归构建子菜单
        Set<MenuDTO> childMenuDTOs = menu.getChildMenus().stream()
                .map(childMenu -> buildMenuHierarchy(childMenu, role))
                .filter(childMenuDTO -> childMenuDTO != null) // 过滤掉跳过的菜单
                .collect(Collectors.toSet());

        // 获取菜单下的按钮组件
        Set<ButtonDTO> buttonDTOs = getButtonComponents(menu, role);

        // 构建菜单DTO
        return new MenuDTO(
                menu.getId(),
                menu.getIdentifier(),
                menu.getType(),
                menu.getDisplayName(),
                menu.getUrl(),
                menu.getIcon(),
                menu.getOrderNum(),
                menu.isVisible(),
                menu.getDescription(),
                menu.isStatus(),
                childMenuDTOs,
                buttonDTOs
        );
    }

    // 获取菜单下的按钮组件，并检查角色是否拥有权限
    private Set<ButtonDTO> getButtonComponents(Menu menu, Role role) {
        Set<ButtonComponent> buttons = buttonComponentRepository.findByParentMenu(menu);

        return buttons.stream()
                .map(button -> {
                    // 如果按钮没有配置任何权限，默认认为角色有访问权限
                    boolean hasAccess = button.getPermissions().isEmpty() ||
                            role.getPermissions().stream()
                                    .anyMatch(permission -> button.getPermissions().contains(permission));

                    Set<PermissionDTO> permissionDTOs = button.getPermissions().stream()
                            .map(permission -> new PermissionDTO(
                                    permission.getId(),
                                    permission.getIdentifier(),
                                    permission.getDisplayName(),
                                    permission.getOrderNum()
                            ))
                            .collect(Collectors.toSet());

                    return new ButtonDTO(
                            button.getId(),
                            button.getIdentifier(),
                            button.isVisible(),
                            button.getDescription(),
                            button.isStatus(),
                            permissionDTOs
                    );
                })
                .collect(Collectors.toSet());
    }



    //////////////////////////
    ///
    /// 基本方法
    ///
    /////////////////////////
    // 为角色绑定菜单
    public Role bindMenusToRole(Long roleId, Set<Long> menuIds) {
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> new RuntimeException("Role not found"));


        List<Menu> menus = menuRepository.findAllById(menuIds);
        if (menus.isEmpty()) {
            throw new RuntimeException("Menus not found");
        }

        // 将 List<Menu> 转换为 Set<Permission>
        Set<Menu> menuSet = new HashSet<>(menus);

        role.setMenus(menuSet);
        return roleRepository.save(role);
    }

    public Set<Menu> getMenusForRole(Long roleId) {
        Role role = roleRepository.findById(roleId)
                .orElseThrow(() -> new RuntimeException("Role not found with ID: " + roleId));

        // 获取角色的顶级菜单（parent_id 为空）
        Set<Menu> topLevelMenus = role.getMenus().stream()
                .filter(menu -> menu.getParentMenu() == null)
                .collect(Collectors.toSet());

        // 递归加载子菜单
        for (Menu menu : topLevelMenus) {
            loadChildMenus(menu);
        }

        return topLevelMenus;
    }

    private void loadChildMenus(Menu menu) {
        // 找到当前菜单的子菜单（parent_id 等于当前菜单 id）
        Set<Menu> childMenus = menuRepository.findByParentMenu_Id(menu.getId());
        menu.setChildMenus(childMenus);

        // 递归加载子菜单
        for (Menu childMenu : childMenus) {
            loadChildMenus(childMenu);
        }
    }



}
